package com.founder.android.sample;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpResponse;
import org.json.JSONException;

import com.founder.android.adapter.WeatherAdapter;
import com.founder.android.cache.MemoryCache;
import com.founder.android.data.GeoData;
import com.founder.android.data.WeatherCondition;
import com.founder.android.data.WeatherInfo;
import com.founder.android.db.City;
import com.founder.android.db.CityStoreService;
import com.founder.android.db.LocationStoreService;
import com.founder.android.http.HttpClientHelper;
import com.founder.android.http.ResponseListener;
import com.founder.android.parser.GeocodeJSONParser;
import com.founder.android.parser.ParserListener;
import com.founder.android.parser.WeatherXMLParserHandler;
import com.founder.android.parser.XMLParserHelper;
import com.founder.android.util.GPSHelper;
import com.founder.android.widget.AsynchronousButton;
import com.google.ads.AdView;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.TextView;
import android.widget.Toast;

public class WeatherActivity extends DBAccessActivity {
	
	//天气数据列表适配器
	private WeatherAdapter adapter;
	
	//添加城市的输入框
	private EditText cityName;
	
	//添加按钮
	private AsynchronousButton addCity;
	
	//刷新按钮
	private AsynchronousButton btnReflash;
	
	//城市数据持久化类
	private CityStoreService cityStoreService;
	
	//选择城市的对话框
	private Dialog dialog;
	
	//删除城市的确认对话框
	private Dialog deleteCityDialog;
	
	//需要删除的城市的index
	private int deleteItemPosition;
	
	//显示当前所在城市
	private TextView currentCity;
	
	//显示天气更新时间
	private TextView updateDate;
	
	private GPSHelper gpsHelper;
	
	private LocationStoreService locationStoreService;
	
	private AdView adView;
	
	/**
	 * 初始化方法
	 */
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.weather_layout);
	    //添加广告数据
		adView = (AdView)findViewById(R.id.adView);
	    
		//初始化城市数据持久化类
		cityStoreService = new CityStoreService(db);
		locationStoreService = new LocationStoreService(db);
		gpsHelper = new GPSHelper(this);
		gpsHelper.openGPS();
		
		/* 询问是否需要打开GPS
		boolean inOpening = gpsHelper.openGPS();
		if (!inOpening) {
			new AlertDialog.Builder(this)
			.setTitle(R.string.title_tip)
			.setMessage(R.string.open_gps)
			.setPositiveButton(//确定按钮
				R.string.ok, new DialogInterface.OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int which) {
					Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
					startActivity(intent);
				}
			})
			.setNegativeButton(R.string.cancel, null)//取消按钮
			.show();
		}
		*/
		
		currentCity = (TextView)findViewById(R.id.current_city);
		updateDate = (TextView)findViewById(R.id.update_date);
		
		//初始化城市对话框
		cityName = new EditText(this);
		dialog = new AlertDialog.Builder(this)
		.setTitle(R.string.input_city_hint_text)
		.setView(cityName)
		.setPositiveButton(//确定按钮
				R.string.ok, new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				saveCity();
			}
		})
		.setNegativeButton(R.string.cancel, null)//取消按钮
		.create();
		
		//初始化删除对话框
		deleteItemPosition = -1;
		deleteCityDialog = new AlertDialog.Builder(this)
		.setTitle(R.string.title_warn)
		.setMessage(R.string.delete_city)
		.setPositiveButton(//确定按钮
				R.string.ok, new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				deleteCity();
			}
		})
		.setNegativeButton(R.string.cancel, null)//取消按钮
		.create();
		
		//初始化添加城市按钮
		addCity = (AsynchronousButton)findViewById(R.id.addCity);
		addCity.setText(getString(R.string.add_city));
		addCity.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				dialog.show();
			}
		});
		
		//初始化刷新按钮
		btnReflash = (AsynchronousButton)findViewById(R.id.reflash);
		btnReflash.setText(getString(R.string.reflash));
		btnReflash.setOnClickListener(reflashClickListener);
		
		//初始化天气列表
		ExpandableListView weatherList = 
			(ExpandableListView)findViewById(R.id.weatherList);
		adapter = new WeatherAdapter(this);
		weatherList.setAdapter(adapter);
		weatherList.setOnItemLongClickListener(deleteItemListener);
		
		//初始化天气数据
		WeatherParserListener parserListener = new WeatherParserListener() {
			@Override
			public void onParseItem(Object data) {
				WeatherInfo info = (WeatherInfo)data;
				setUpdateDate(info.getCurrentDateTime());
				adapter.addData(info);
			}
		};
		List<City> citys = cityStoreService.findAll();
		try {
			for (City city : citys) {
				String fileName = city.getFileName();
				//Log.d("WeatherActivity", "fileName=" + fileName);
				File file = new File(getCacheDir(), fileName);
				if (file != null && file.exists()) {
					FileInputStream in = new FileInputStream(file);
					XMLParserHelper.parse(in, new WeatherXMLParserHandler(), parserListener);
				} else {
					WeatherCondition currentCondition = new WeatherCondition();
					currentCondition.setCondition(getString(R.string.no_data));
					
					WeatherInfo info = new WeatherInfo();
					info.setPostalCode(city.getName());
					info.setCurrentCondition(currentCondition);
					adapter.addData(info);
				}
			}
		} catch (FileNotFoundException e) {
    		Log.e("WeatherActivity", "XML File Parse Failed!", e);
    		Toast.makeText(WeatherActivity.this, "XML File Parse Failed!", Toast.LENGTH_SHORT).show();
		}
		com.founder.android.db.Location dbLocation = locationStoreService.find();
		if (dbLocation != null) {
			setCurrentCityText(dbLocation.getName());
		}
	}
	
	private void setCurrentCityText(String text) {
		currentCity.setText(text);
	}
	
	@Override
	protected void onResume() {
		super.onResume();
		if (checkNeedReflashCity()) {
			reflashCity();
		}
	}
	
	@Override
	public void onDestroy() {
		adView.destroy();
		super.onDestroy();
	}
	
	private void deleteCity() {
		List<WeatherInfo> datas = adapter.getDatas();
		WeatherInfo info = datas.get(deleteItemPosition);
		String code = info.getPostalCode();
		City city = cityStoreService.findByName(code);
		if (city != null) {
			String fileName = city.getFileName();
			File file = new File(getCacheDir(), fileName);
			if (file != null && file.exists()) {
				file.delete();
			}
			cityStoreService.remove(city.getId());
		}
		adapter.removeData(info);
	}
	
	private AdapterView.OnItemLongClickListener deleteItemListener = new AdapterView.OnItemLongClickListener() {

		@Override
		public boolean onItemLongClick(AdapterView<?> parent, 
				View view, int position, long id) {
			deleteItemPosition = position;
			deleteCityDialog.show();
			return true;//已经处理过了
		}
		
	};
	
	private void reflashCity() {
		Location location = gpsHelper.getLocationOnce();
		if (location == null) {
			return;
		}
		double latitude = location.getLatitude();
        double longitude= location.getLongitude();
		String url = GeocodeJSONParser.getUrl(latitude, longitude);
		Log.d("WeatherActivity", "city url=" + url);
		HttpClientHelper.asyncGetTextRequest(this, url, new CityXMLResponseListener());
	}
	
	private boolean checkNeedReflashCity() {
		com.founder.android.db.Location dbLocation = locationStoreService.find();
		if (dbLocation == null) {
			return true;
		}
		
		Location location = gpsHelper.getLocationOnce();
		if (location == null) {
			return false;
		}
		
		float[] results = new float[1];
		Location.distanceBetween(dbLocation.getLat(), dbLocation.getLng(), 
				location.getLatitude(), location.getLongitude(), results);
		Log.d("WeatherActivity", String.format("DB(%.6f, %.6f), GPS(%.6f, %.6f), Distance:%.0f", dbLocation.getLat(), dbLocation.getLng(), location.getLatitude(), location.getLongitude(), results[0]));
		return (results[0] > 100 * 1000);
	}
	
	private void setUpdateDate(String text) {
		updateDate.setText(getString(R.string.update_at) + text);
	}
	
	/**
	 * 点击刷新按钮
	 */
	private OnClickListener reflashClickListener = new OnClickListener() {
		
		List<WeatherInfo> weatherInfos = new ArrayList<WeatherInfo>();
		
		@Override
		public void onClick(View v) {
			
			
			List<City> citys = cityStoreService.findAll();
			final int citySize = citys.size();
			if (citySize > 0) {
				btnReflash.setEnabled(false);
				weatherInfos.clear();
				
				WeatherParserListener parserListener = new WeatherParserListener() {
					@Override
					public void onParseItem(Object data) {
						WeatherInfo info = (WeatherInfo)data;
						weatherInfos.add(info);
						if (weatherInfos.size() == citySize) {
							setUpdateDate(info.getCurrentDateTime());
							adapter.setDatas(weatherInfos);
							btnReflash.setEnabled(true);
						}
					}
				};
				
				XmlDownLoadResponseListener downListener = new XmlDownLoadResponseListener(parserListener);
				for (City city : citys) {
					String cityName = city.getName();
					String url = WeatherXMLParserHandler.getRequestURL(cityName);
					File file = new File(getCacheDir(), MemoryCache.getHash(cityName));
					HttpClientHelper.asyncDownFileRequest(WeatherActivity.this, url, file, WeatherXMLParserHandler.RESPONSE_CHARSET, downListener);
				}
			}
		}
	};

	/**
	 * 添加一个新城市的天气
	 */
	private void saveCity() {
		String name = cityName.getText().toString();
		if ("".equals(name.trim())) {
			return;
		}
		addCity.setEnabled(false);
		String url = WeatherXMLParserHandler.getRequestURL(name);
		File file = new File(getCacheDir(), MemoryCache.getHash(name));
		WeatherParserListener parserListener = new WeatherParserListener() {
			@Override
			public void onParseItem(Object data) {
				addCity.setEnabled(true);
				WeatherInfo info = (WeatherInfo)data;
				if (!info.isSuccess()) {
					Log.e("WeatherActivity", "Weather data has a problem:" + info.getProblem());
					Toast.makeText(WeatherActivity.this, "Weather data has a problem:" + info.getProblem(), Toast.LENGTH_SHORT).show();
					return;
				}
				String cityName = info.getPostalCode();
				City city = new City(cityName, MemoryCache.getHash(cityName));
				cityStoreService.save(city);
				adapter.addData(info);
				setUpdateDate(info.getCurrentDateTime());
			}
		};
		XmlDownLoadResponseListener downListener = new XmlDownLoadResponseListener(parserListener);
		HttpClientHelper.asyncDownFileRequest(this, url, file, 
				WeatherXMLParserHandler.RESPONSE_CHARSET, downListener);
	}
	
	private class CityXMLResponseListener implements ResponseListener {
		
		CityXMLResponseListener() {}
		
		@Override
		public void onResponseSuccess(HttpResponse response, Object result) {
			//Log.d("WeatherActivity", "Request Success URL:" + url + " !");
			String json = (String)result;
			try {
				GeoData geoData = GeocodeJSONParser.parser(json);
				if (geoData != null) {
					String city = geoData.getAddress();
					String name = GeocodeJSONParser.formatCity(city);
					setCurrentCityText(name);
					com.founder.android.db.Location location = new com.founder.android.db.Location();
					location.setName(name);
					location.setLat(Double.parseDouble(geoData.getLat()));
					location.setLng(Double.parseDouble(geoData.getLng()));
					locationStoreService.saveLocation(location);
				}
			} catch (JSONException e) {
				Log.e("WeatherActivity", "City Parser Failed !", e);
				Toast.makeText(WeatherActivity.this, "City Parser Failed!", Toast.LENGTH_SHORT).show();
			}

		}
				
		@Override
		public void onResponseFailed(HttpResponse response, Throwable error) {
			Log.e("WeatherActivity", "City Request Failed !", error);
			Toast.makeText(WeatherActivity.this, "City Request Failed!", Toast.LENGTH_SHORT).show();
		}
	}
	
	/**
	 * 下载天气数据的回调
	 * @author chen_weihua
	 *
	 */
	private class XmlDownLoadResponseListener implements ResponseListener {
		
		private ParserListener weatherParser;
		
		XmlDownLoadResponseListener(ParserListener weatherParser) {
			this.weatherParser = weatherParser;
		}
		
    	@Override
    	public void onResponseFailed(HttpResponse response, Throwable error) {
    		btnReflash.setEnabled(true);
    		addCity.setEnabled(true);
    		Log.e("WeatherActivity", "XML File Down Failed!", error);
    		Toast.makeText(WeatherActivity.this, "XML File Down Failed!", Toast.LENGTH_SHORT).show();
    	}

    	@Override
    	public void onResponseSuccess(HttpResponse response, Object result) {
    		File file = (File)result;
    		Log.i("WeatherActivity", "XML File Down success!");
    		try {
				FileInputStream in = new FileInputStream(file);
				XMLParserHelper.parse(in, new WeatherXMLParserHandler(), weatherParser);
			} catch (FileNotFoundException e) {
	    		Log.e("WeatherActivity", "XML File Parse Failed!", e);
	    		Toast.makeText(WeatherActivity.this, "XML File Parse Failed!", Toast.LENGTH_SHORT).show();
			}
    	}
    };
    
    /**
     * 解析天气数据的回调
     * @author chen_weihua
     *
     */
    private class WeatherParserListener implements ParserListener {
		@Override
		public void onParseBegin() {
			;
		}
		
		@Override
		public void onParseItem(Object data) {
			;
		}

		@Override
		public void onParseEnd() {
			;
		}
    	
		@Override
		public void onParseFailed(Throwable error) {
			btnReflash.setEnabled(true);
			addCity.setEnabled(true);
			Log.e("WeatherActivity", "XML Parse Failed!", error);
			Toast.makeText(WeatherActivity.this, "XML Parse Failed!", Toast.LENGTH_SHORT).show();
		}
    }
}
